package com.cxt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cxt.Mapper.CarpoolInfoMapper;
import com.cxt.constant.CarpoolConstant;
import com.cxt.constant.WaypointConstant;
import com.cxt.context.BaseContext;
import com.cxt.dto.CarpoolAddDto;
import com.cxt.dto.CarpoolInfoDto;
import com.cxt.dto.CarpoolTjDto;
import com.cxt.entity.*;
import com.cxt.exception.BaseException;
import com.cxt.service.*;
import com.cxt.utils.DistanceUtil;
import com.cxt.vo.CarpoolInfoVo;
import com.cxt.vo.CarpoolPreviewVo;
//import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 拼车信息表 服务实现类
 * </p>
 *
 * @author baomidou
 * @since 2025-02-27
 */
@Service
public class CarpoolInfoServiceImpl extends ServiceImpl<CarpoolInfoMapper, CarpoolInfo> implements ICarpoolInfoService {
    //途径点
    @Autowired
    private  WaypointInfoServiceImpl waypointInfoService;
    //雪花算法ID
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private IMessageNotificationService messageNotificationService;
    @Autowired
    private ITripInfoService tripInfoService;
    @Autowired
    private StudentInfoService userInfoService;
    @Override
    public void addCarpoolInfo(CarpoolInfo carpoolInfo) {
        this.save(carpoolInfo);
    }

    @Override
    /**
     * 添加拼车信息
     * 功能概要：获取用户ID，然后添加起点终点信息
     *         获取起点终点信息ID，设置到拼车信息中
     *         保存拼车信息
     */
    @Transactional
    public Boolean addCarpoolInfo(CarpoolInfoDto carpoolInfoDto) {
        //获取用户ID
        Long userId = BaseContext.getCurrentId();
        //封装起点终点信息
        //拼车ID
        Long carpoolInfoId = idGeneratorService.generateId();
        //起点ID
        Long startId = idGeneratorService.generateId();
        //终点ID
        Long endId = idGeneratorService.generateId();
        //传入拼车ID，起点ID，拼车信息。返回途径点对象
        WaypointInfo startWaypointInfo = this.fromWaypointInfo(carpoolInfoId, null,startId, endId,carpoolInfoDto);
        WaypointInfo endWaypointInfo = this.fromWaypointInfo(carpoolInfoId, startId,endId, null,carpoolInfoDto);
        //封装拼车信息
        //传入拼车ID，起点ID，终点ID，拼车信息。返回途径点对象
        CarpoolInfo carpoolInfo = this.formCarpoolInfo(carpoolInfoId,carpoolInfoDto);
        //保存拼车信息
        this.save(carpoolInfo);
        //保存起点终点信息
        waypointInfoService.save(startWaypointInfo);
        waypointInfoService.save(endWaypointInfo);
        return true;
    }

    /**
     * 构建拼车信息
     * @param carpoolInfoId
     * @param carpoolInfoDto
     * @return
     */
    private CarpoolInfo formCarpoolInfo(Long carpoolInfoId, CarpoolInfoDto carpoolInfoDto) {
        CarpoolInfo carpoolInfo = CarpoolInfo.builder()
                .id(carpoolInfoId)
                //团长ID：人找车用户ID就是团长ID
                .groupLeaderId(carpoolInfoDto.getCarpoolType()== CarpoolConstant.CARPOOL_TYPE_PERSON_FIND_CAR
                        ? BaseContext.getCurrentId()
                        : null)
                //司机ID：车找人用户ID就是司机ID
                .driverId(carpoolInfoDto.getCarpoolType()== CarpoolConstant.CARPOOL_TYPE_CAR_FIND_PERSON
                        ? BaseContext.getCurrentId()
                        : null)
                .memberIds(null)
                //标题
                .title(carpoolInfoDto.getTitle())
                .description(carpoolInfoDto.getDescription())
                //总距离
                .totalDistance(carpoolInfoDto.getTotalDistance())
                //预计用时
                .estimatedDuration(carpoolInfoDto.getEstimatedDuration())
                //拼车状态
                .carpoolStatus(CarpoolConstant.CARPOOL_STATUS_IN_PROGRESS)
                //拼车类型
                .carpoolType(carpoolInfoDto.getCarpoolType())
                //理想人数
                .idealPersonCount(carpoolInfoDto.getIdealPersonCount())
                //乘客人数
                .passengerCount(carpoolInfoDto.getPassengerCount())
                //计划开始时间
                .plannedStartTime(carpoolInfoDto.getPlannedStartTime())
                //定价方式
                .pricingMethod(carpoolInfoDto.getPricingMethod())
                //公里单价
                .pricePerKm(carpoolInfoDto.getPricePerKm())
                //一口价
                .flatRate(carpoolInfoDto.getFlatRate())
                //是否包含过路费
                .includeTollFee(true)
                //过路费
                .tollFee(carpoolInfoDto.getIncludeTollFee() ?
                        carpoolInfoDto.getTollFee()
                        : null)
                //总价计算：按公里的话需要加过路费，一口价不加过路费
                .totalPrice(carpoolInfoDto.getPricingMethod()== CarpoolConstant.PRICING_METHOD_PER_KM
                        ? carpoolInfoDto.getTotalDistance().multiply(carpoolInfoDto.getPricePerKm())
                        .add(carpoolInfoDto.getTollFee())
                        : carpoolInfoDto.getFlatRate().add( new BigDecimal(0)))
                .paymentCalculationMethod(carpoolInfoDto.getPaymentCalculationMethod())
                .build();
        return carpoolInfo;
    }

    /**
     * 构建途径点信息
     * @param carpoolInfoId
     * @param startId
     * @param endId
     * @param carpoolInfoDto
     * @return
     */
    private WaypointInfo fromWaypointInfo(Long carpoolInfoId, Long startId, Long wayId, Long endId, CarpoolInfoDto carpoolInfoDto) {
        WaypointInfo waypointInfo = WaypointInfo.builder()
                // 雪花算法生成ID
                .id(wayId)
                .userId(BaseContext.getCurrentId())
                // 拼车信息ID
                .carpoolInfoId(carpoolInfoId)
                // 动态设置起点或终点信息
                .longitude(startId == null ? carpoolInfoDto.getEndLongitude() : carpoolInfoDto.getStartLongitude())
                .latitude(startId == null ? carpoolInfoDto.getEndLatitude() : carpoolInfoDto.getStartLatitude())
                .locationName(startId == null ? carpoolInfoDto.getEndLocationName() : carpoolInfoDto.getStartLocationName())
                // 乘客人数
                .passengerCount(carpoolInfoDto.getPassengerCount())
                // 途径点状态（未送达）
                .status(WaypointConstant.WAYPOINT_STATUS_UNREACHED)
                // 起点是1，终点是3
                .waypointType(startId == null ? 1 : 3)
                // 下一点ID
                .nextWaypointId(endId)
                // 上一点ID
                .prevWaypointId(startId)
                // 途径点索引：默认使用链表所以设置不使用索引
                .waypointIndex(0)
                // 新增：设置tripId为null
                .tripId(null)
                .build();
        return waypointInfo;
    }
    @Override
    public List<CarpoolPreviewVo> previewCarpoolInfo() {
        //返回类表
        List<CarpoolPreviewVo> carpoolPreviewVoList = new ArrayList<>();
        //获取所有拼车信息，并根据创建时间倒叙
//        List<CarpoolInfo> carpoolInfoList = this.list();
        //拼车状态是1的拼车信息
        LambdaQueryWrapper<CarpoolInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CarpoolInfo::getCarpoolStatus, CarpoolConstant.CARPOOL_STATUS_IN_PROGRESS);
        List<CarpoolInfo> carpoolInfoList = this.list(queryWrapper);
        //根据创建时间倒叙
        carpoolInfoList.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
        //遍历拼车信息
        for (CarpoolInfo carpoolInfo : carpoolInfoList) {
            //获取拼车信息ID
            Long carpoolInfoId = carpoolInfo.getId();
            //获取途径点信息
            List<WaypointInfo> waypointInfoList = waypointInfoService.getWaypointInfoByCarpoolId(carpoolInfoId);
            Boolean isInCarpool = false;
            //如果途径点里面的userid和当前用户相同，就表示在该拼车中
            for (WaypointInfo waypointInfo : waypointInfoList) {
                if (waypointInfo.getUserId().equals(BaseContext.getCurrentId())) {
                    //设置是否在拼车中
                    isInCarpool = true;
                    break;
                }
            }
            //组装预览信息
            CarpoolPreviewVo carpoolPreviewVo = CarpoolPreviewVo.fromCarpoolInfoAndWaypoints(carpoolInfo, waypointInfoList,isInCarpool);
            //添加到列表中
            carpoolPreviewVoList.add(carpoolPreviewVo);
        }
        //是否在拼车中排序
        carpoolPreviewVoList.sort((o1, o2) -> {
            if (o1.getIsInCarpool() && !o2.getIsInCarpool()) {
                return -1;
            } else if (!o1.getIsInCarpool() && o2.getIsInCarpool()) {
                return 1;
            } else {
                return o2.getIsInCarpool().compareTo(o1.getIsInCarpool());
            }
        });
        //返回列表
        return carpoolPreviewVoList;
    }

    @Override
    public List<CarpoolPreviewVo> previewCarpoolInfoByID() {
        //根据ID获取拼车信息
        Long userId = BaseContext.getCurrentId();
        LambdaQueryWrapper<CarpoolInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CarpoolInfo::getGroupLeaderId, userId)
                .or()
                .eq(CarpoolInfo::getDriverId, userId);
        //返回类表
        List<CarpoolPreviewVo> carpoolPreviewVoList = new ArrayList<>();
        //获取所有拼车信息，并根据创建时间倒叙
        List<CarpoolInfo> carpoolInfoList = this.list(queryWrapper);
        //根据创建时间倒叙
        carpoolInfoList.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
        //遍历拼车信息
        for (CarpoolInfo carpoolInfo : carpoolInfoList) {
            //获取拼车信息ID
            Long carpoolInfoId = carpoolInfo.getId();
            //获取途径点信息
            List<WaypointInfo> waypointInfoList = waypointInfoService.getWaypointInfoByCarpoolId(carpoolInfoId);
            Boolean isInCarpool = false;
            for (WaypointInfo waypointInfo : waypointInfoList) {
                if (waypointInfo.getUserId().equals(BaseContext.getCurrentId())) {
                    //设置是否在拼车中
                    isInCarpool = true;
                    break;
                }
            }
            Boolean isGroupLeader = false;
            //组装预览信息
            CarpoolPreviewVo carpoolPreviewVo = CarpoolPreviewVo.fromCarpoolInfoAndWaypoints(carpoolInfo, waypointInfoList,isInCarpool);
            //添加到列表中
            carpoolPreviewVoList.add(carpoolPreviewVo);
        }
        //返回列表
        return carpoolPreviewVoList;
    }

    @Override
    public CarpoolInfoVo getCarpoolInfoByID(Long id) {
        //创建一个条件查询器
        LambdaQueryWrapper<CarpoolInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CarpoolInfo::getId, id);
        List<WaypointInfo> waypointInfoByCarpoolId = waypointInfoService.getWaypointInfoByCarpoolId(id);
        //如果途径点的userid和当前用户相同，就表示在该拼车中
        Boolean isInCarpool = false;
        for (WaypointInfo waypointInfo : waypointInfoByCarpoolId) {
            if (waypointInfo.getUserId().equals(BaseContext.getCurrentId())) {
                isInCarpool = true;
                break;
            }
        }
        CarpoolInfo one = this.getOne(queryWrapper);
        //如果是司机的话，直接设置成true
        if (one.getDriverId()!=null&&one.getDriverId().equals(BaseContext.getCurrentId())) {
            isInCarpool = true;
        }
        return CarpoolInfoVo.builder()
                .carpoolInfo(one)
                .waypointInfos(waypointInfoByCarpoolId)
                .isInCarpool(isInCarpool)
                .build();
    }

    /**
     * 用户加入拼车
     * @param carpoolAddDto
     * @return
     */
    @Override
    @Transactional
    public Boolean addCarpoolInfo(CarpoolAddDto carpoolAddDto) {
        //判断身份
        //如果是乘客，则调用乘客加入方法
        //如果是司机，则调用司机加入方法
        if(carpoolAddDto.getJoinIdentity()== CarpoolConstant.JOIN_IDENTITY_PASSENGER){
            //乘客加入方法
            Boolean b = addPassenger(carpoolAddDto);
        }else{
            Boolean b = addDriver(carpoolAddDto);
        }
        //判断拼车是否结束
        CarpoolInfo carpoolInfo = this.getById(carpoolAddDto.getCarpoolInfoId());
        if(carpoolInfo.getPassengerCount().equals(carpoolInfo.getIdealPersonCount())
                //司机id不为空
                && carpoolInfo.getDriverId() != null){
            //拼车人数达到上限，拼车已满
            carpoolInfo.setCarpoolStatus(CarpoolConstant.CARPOOL_STATUS_FULL);
            this.updateById(carpoolInfo);
            addTripInfo(carpoolInfo);
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean removeUser(CarpoolAddDto carpoolAddDto) {
        // 获取拼车信息
        CarpoolInfo carpoolInfo = this.getById(carpoolAddDto.getCarpoolInfoId());
        if (carpoolInfo == null) {
            throw new RuntimeException("拼车信息不存在");
        }
        
        // 处理memberIds
        List<Long> memberIds = carpoolInfo.getMemberIds() != null 
            ? Arrays.stream(carpoolInfo.getMemberIds().split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList()) 
            : new ArrayList<>();
        
        if (!memberIds.remove(carpoolAddDto.getUserId())) {
            throw new RuntimeException("用户不在拼车信息中");
        }
        
        carpoolInfo.setMemberIds(String.join(",", memberIds.stream().map(String::valueOf).collect(Collectors.toList())));
        
        // 查询并删除途径点
        LambdaQueryWrapper<WaypointInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WaypointInfo::getCarpoolInfoId, carpoolAddDto.getCarpoolInfoId())
                    .eq(WaypointInfo::getUserId, carpoolAddDto.getUserId());
        List<WaypointInfo> waypoints = waypointInfoService.list(queryWrapper);
        
        // 计算需要减少的乘客数
        int passengerToRemove = waypoints.stream()
                                        .mapToInt(WaypointInfo::getPassengerCount)
                                        .sum();
        
        // 删除途径点
        waypointInfoService.remove(queryWrapper);
        
        // 更新拼车信息
        carpoolInfo.setPassengerCount(carpoolInfo.getPassengerCount() - passengerToRemove);
        carpoolInfo.setCarpoolStatus(CarpoolConstant.CARPOOL_STATUS_IN_PROGRESS);
        
        return this.updateById(carpoolInfo);
    }

    @Override
    @Transactional
    public Boolean removeJoin(Long id) {
        //判断该用户是在拼车中是什么？1，团长，2，司机，3，乘客
        CarpoolInfo byId = this.getById(id);
        LambdaQueryWrapper<WaypointInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WaypointInfo::getCarpoolInfoId, id);
        List<WaypointInfo> list = waypointInfoService.list(queryWrapper);
        Integer  joinIdentity = 0;
        for (WaypointInfo waypointInfo : list){
            if (waypointInfo.getUserId().equals(BaseContext.getCurrentId())){
                joinIdentity = 3;
                break;
            }
        }
        if (byId.getGroupLeaderId()!=null&&byId.getGroupLeaderId().equals(BaseContext.getCurrentId())){
            joinIdentity = 1;
        }else if(byId.getDriverId()!=null&&byId.getDriverId().equals(BaseContext.getCurrentId())){
            joinIdentity = 2;
        }
        if(joinIdentity == 0){
            return false;
        }
        //团长的话，直接删除拼车信息
        if(joinIdentity == 1){
            //删除拼车信息和途径点
            this.removeById(id);
            waypointInfoService.remove(queryWrapper);
            //给所以人发送拼车取消的通知
            for (WaypointInfo waypointInfo : list) {
                if(waypointInfo.getWaypointType()==3||waypointInfo.getWaypointType()==1){
                    //不给团长发
                    continue;
                }
                messageNotificationService.addMassage(waypointInfo.getUserId(),"您参与的拼车已被团长取消，请注意查看");
                //如果有司机的话给司机发
                if(byId.getDriverId()!=null){
                    messageNotificationService.addMassage(byId.getDriverId(),"您参与拼车的拼车已被团长取消，请注意查看");
                }
            }
        }else if(joinIdentity == 2){
            //司机id清空
            LambdaUpdateWrapper<CarpoolInfo> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(CarpoolInfo::getId,byId.getId())
                    .set(CarpoolInfo::getDriverId,null);
            this.update(wrapper);
        }else if (joinIdentity == 3) {
            //根据途径点信息计算该用户在拼车中的人数
            int passengerCount = 0;
            for (WaypointInfo waypointInfo : list) {
                if (waypointInfo.getUserId().equals(BaseContext.getCurrentId())){
                    passengerCount = waypointInfo.getPassengerCount();
                }
            }
            byId.setPassengerCount(byId.getPassengerCount() - passengerCount);
            // 将 memberIds 转换为 List，移除特定的 ID，再转换回字符串
            String updatedMemberIds = Arrays.stream(byId.getMemberIds().split(","))
                    .filter(ids -> !ids.equals(BaseContext.getCurrentId().toString()))
                    .collect(Collectors.joining(","));
            byId.setMemberIds(updatedMemberIds);
            this.updateById(byId);
            queryWrapper.eq(WaypointInfo::getUserId, BaseContext.getCurrentId());
            waypointInfoService.remove(queryWrapper);
        }
        return true;
        //修改拼车人数
        //修改用户ids
    }

    @Override
    public List<CarpoolPreviewVo> previewCarpoolInfoByStart(CarpoolTjDto carpoolInfoDto) {
        List<CarpoolPreviewVo> carpoolPreviewVoList = new ArrayList<>();
        //拼车状态是1的拼车信息
        //查询未送达的起点位置在搜索范围内的拼车信息
        LambdaQueryWrapper<WaypointInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WaypointInfo::getWaypointType, 3)
                .eq(WaypointInfo::getStatus, 1)
                .ge(WaypointInfo::getLongitude, carpoolInfoDto.getStartLongitude().subtract(new BigDecimal("0.006")))
                .le(WaypointInfo::getLongitude, carpoolInfoDto.getStartLongitude().add(new BigDecimal("0.006")))
                .ge(WaypointInfo::getLatitude, carpoolInfoDto.getStartLatitude().subtract(new BigDecimal("0.006")))
                .le(WaypointInfo::getLatitude, carpoolInfoDto.getStartLatitude().add(new BigDecimal("0.006")))
                .orderByAsc(WaypointInfo::getLongitude)
                .orderByAsc(WaypointInfo::getLatitude);
        List<WaypointInfo> waypointInfoList = waypointInfoService.list(queryWrapper);
        //查询终点的起点位置
        LambdaQueryWrapper<WaypointInfo> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(WaypointInfo::getWaypointType, 1)
                .eq(WaypointInfo::getStatus, 1)
                .ge(WaypointInfo::getLongitude, carpoolInfoDto.getEndLongitude().subtract(new BigDecimal("0.007")))
                .le(WaypointInfo::getLongitude, carpoolInfoDto.getEndLongitude().add(new BigDecimal("0.007")))
                .ge(WaypointInfo::getLatitude, carpoolInfoDto.getEndLatitude().subtract(new BigDecimal("0.007")))
                .le(WaypointInfo::getLatitude, carpoolInfoDto.getEndLatitude().add(new BigDecimal("0.007")))
                .orderByAsc(WaypointInfo::getLongitude)
                .orderByAsc(WaypointInfo::getLatitude);
        List<WaypointInfo> waypointInfoList1 = waypointInfoService.list(queryWrapper1);
        // 提取两个列表中的拼车ID
        Set<Long> startCarpoolIds = waypointInfoList.stream()
                .map(WaypointInfo::getCarpoolInfoId) // 假设 WaypointInfo 有一个 getCarpoolId 方法
                .collect(Collectors.toSet());

        Set<Long> endCarpoolIds = waypointInfoList1.stream()
                .map(WaypointInfo::getCarpoolInfoId) // 假设 WaypointInfo 有一个 getCarpoolId 方法
                .collect(Collectors.toSet());
        // 计算两个ID集合的交集
        Set<Long> commonCarpoolIds = new HashSet<>(startCarpoolIds);
        commonCarpoolIds.retainAll(endCarpoolIds);
        // 如果交集为空，直接返回空列表
        if (commonCarpoolIds.isEmpty()) {
            return carpoolPreviewVoList;
        }
        //获取set里面的所有拼车信息
        List<CarpoolInfo> carpoolInfoList = this.listByIds(commonCarpoolIds);
        //只保存状态是1的拼车

        // 只保存状态是1的拼车
        carpoolInfoList = carpoolInfoList.stream()
                .filter(carpoolInfo -> carpoolInfo.getCarpoolStatus() == 1)
                .collect(Collectors.toList());

        // 遍历拼车信息
        for (CarpoolInfo carpoolInfo : carpoolInfoList) {
            // 获取拼车信息ID
            Long carpoolInfoId = carpoolInfo.getId();

            // 获取途径点信息
            List<WaypointInfo> waypointInfoListForCarpool = waypointInfoService.getWaypointInfoByCarpoolId(carpoolInfoId);

            // 检查当前用户是否在该拼车中
            Boolean isInCarpool = waypointInfoListForCarpool.stream()
                    .anyMatch(waypointInfo -> waypointInfo.getUserId().equals(BaseContext.getCurrentId()));

            // 组装预览信息
            CarpoolPreviewVo carpoolPreviewVo = CarpoolPreviewVo.fromCarpoolInfoAndWaypoints(carpoolInfo, waypointInfoListForCarpool, isInCarpool);

            // 添加到列表中
            carpoolPreviewVoList.add(carpoolPreviewVo);
        }

        // 是否在拼车中排序
        carpoolPreviewVoList.sort((o1, o2) -> {
            if (o1.getIsInCarpool() && !o2.getIsInCarpool()) {
                return -1;
            } else if (!o1.getIsInCarpool() && o2.getIsInCarpool()) {
                return 1;
            } else {
                return o2.getIsInCarpool().compareTo(o1.getIsInCarpool());
            }
        });

        // 返回列表
        return carpoolPreviewVoList;
    }


    private void addTripInfo(CarpoolInfo carpoolInfo) {
        //获取途径点
        LambdaQueryWrapper<WaypointInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WaypointInfo::getCarpoolInfoId, carpoolInfo.getId());
        List<WaypointInfo> waypointInfoList = waypointInfoService.list(queryWrapper);
        List<Long> waypointIds = waypointInfoList.stream()
                .map(WaypointInfo::getId)
                .collect(Collectors.toList());
        //转成字符格式
        String waypointIdsStr = String.join(",", waypointIds.stream()
                .map(String::valueOf).collect(Collectors.toList()));
        TripInfo tripInfo = TripInfo.builder()
                .carpoolInfoId(carpoolInfo.getId())
                .driverId(carpoolInfo.getDriverId())
                .groupLeaderId(carpoolInfo.getGroupLeaderId())
                .memberIds(carpoolInfo.getMemberIds())
                .waypointIds(waypointIdsStr)
                .passedWaypoints(null)
                .estimatedStartTime(carpoolInfo.getPlannedStartTime())
                .tripStatus(1)
                .startTime(null)
                .endTime(null)
                .traveledDistance(null)
                .build();
        
        // 保存行程信息
        tripInfoService.save(tripInfo);
        for (WaypointInfo waypointInfo : waypointInfoList) {
            waypointInfo.setTripId(tripInfo.getId());
            waypointInfoService.updateById(waypointInfo);
        }
        // 给所有行程里的人员发送拼车成功信息
        for (Long waypointId : waypointIds) {
            messageNotificationService.addMassage(waypointId,"您的拼车已成功，请注意查看行程信息");
        }
        //给司机发一个
        messageNotificationService.addMassage(carpoolInfo.getDriverId(),"司机您好，拼车已成功，请合理安排接驾时间");
    }

    /**
     * 乘客
     * @param carpoolAddDto
     * @return
     */
    private Boolean addPassenger(CarpoolAddDto carpoolAddDto) {
        //判断数据合理
        if(carpoolAddDto.getCarpoolInfoId()==null
                || carpoolAddDto.getUserId()==null
                || carpoolAddDto.getJoinIdentity()==null
                || carpoolAddDto.getJoinCount()==null
                || carpoolAddDto.getStartLongitude()==null
                || carpoolAddDto.getStartLatitude()==null
                || carpoolAddDto.getStartLocationName()==null
                || carpoolAddDto.getEndLongitude()==null
        ){
            //抛出加入数据异常
            throw new BaseException("加入失败，请重新尝试");
        }
        //获取拼车信息
        CarpoolInfo carpoolInfo = this.getById(carpoolAddDto.getCarpoolInfoId());
        //是否终点距离限制
        if(true){
            //获取起点终点信息：拼车信息ID，途径点类型
            LambdaQueryWrapper<WaypointInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WaypointInfo::getCarpoolInfoId, carpoolAddDto.getCarpoolInfoId())
                    //终点
                    .eq(WaypointInfo::getWaypointType, 1);
            WaypointInfo waypointInfoList = waypointInfoService.getOne(queryWrapper);
            if(waypointInfoList==null){
                //抛出加入数据异常
                throw new BaseException("系统数据异常，拼车终点异常");
            }else{
                //计算两点之间的距离
                double distance = DistanceUtil.calculateDistanceByLonLat(carpoolAddDto.getEndLongitude().doubleValue(),
                        carpoolAddDto.getEndLatitude().doubleValue(),
                        waypointInfoList.getLongitude().doubleValue(),
                        waypointInfoList.getLatitude().doubleValue());
                        //如果大于5km，则返回加入数据异常
                if(distance/1000>CarpoolConstant.JOIN_DISTANCE_LIMIT.doubleValue()){
                    //抛出加入数据异常
                    throw new BaseException("加入失败，终点距离过远") {
                    };
                }
            }
        }
        //判断拼车人数限制
        //判断人数是否超过：乘客人数+新加入人数<拼车总人数
        if(carpoolInfo.getPassengerCount()+carpoolAddDto.getJoinCount()>carpoolInfo.getIdealPersonCount()){
            //抛出加入数据异常
            throw new BaseException("加入失败，人数已满") {
            };
        }
        //判断拼车状态
        if(carpoolInfo.getCarpoolStatus()!=CarpoolConstant.CARPOOL_STATUS_IN_PROGRESS){
            //抛出加入数据异常
            throw new BaseException("加入失败，拼车已完成"){};
        }
        //添加途径点
        Long newWaypointId = idGeneratorService.generateId();
        WaypointInfo waypointInfo2 = WaypointInfo.builder()
                .id(newWaypointId)
                .carpoolInfoId(carpoolAddDto.getCarpoolInfoId())
                .userId(carpoolAddDto.getUserId())
                .longitude(carpoolAddDto.getEndLongitude())
                .latitude(carpoolAddDto.getEndLatitude())
                .locationName(carpoolAddDto.getEndLocationName())
                .waypointType(2)
                .waypointIndex(null)
                .prevWaypointId(null)
                .nextWaypointId(null)
                .passengerCount(carpoolAddDto.getJoinCount())
                .status(CarpoolConstant.WAYPOINT_STATUS_UNREACHED)
                .build();
        waypointInfoService.save(waypointInfo2);
        //修改拼车信息
        //设置乘客数量
        carpoolInfo.setPassengerCount(carpoolInfo.getPassengerCount()+carpoolAddDto.getJoinCount());
        //设置乘客ids
        carpoolInfo.setMemberIds((carpoolInfo.getMemberIds()!=null?carpoolInfo.getMemberIds()+",":"")+carpoolAddDto.getUserId());
        return this.updateById(carpoolInfo);
    }

    private Boolean addDriver(CarpoolAddDto carpoolAddDto) {
        //添加司机
        //获取拼车信息判断司机Id是否为空
        CarpoolInfo carpoolInfo = this.getById(carpoolAddDto.getCarpoolInfoId());
        if(carpoolInfo.getDriverId()!=null){
            //抛出加入数据异常
            throw new RuntimeException("加入失败，已有司机");
        }
        //没有司机，则添加司机
        carpoolInfo.setDriverId(BaseContext.getCurrentId());
        return this.updateById(carpoolInfo);
    }
}
